在現代雲原生應用程式中,跨多個 Kubernetes 叢集部署和管理服務變得越來越普遍。Google Kubernetes Engine (GKE) 提供了強大的功能來簡化這個過程,其中 GKE Fleet 和 Multi-cluster Services (MCS) 是兩個關鍵技術。
本文將深入探討如何利用 Shared VPC 在 GKE Fleet 中設置 MCS,實現跨不同區域叢集的服務發現和流量管理。此架構不僅提升了應用程式的可用性和容錯能力,也簡化了網路管理的複雜度,讓您可以更專注於應用程式的開發和部署。 無論您是 Kubernetes 新手還是經驗豐富的用戶,本文都將提供您在 GKE 環境中建構和管理多叢集服務的實用知識。
GKE 多叢集服務 (Multi-Cluster Services,MCS) 允許您在多個 Google Kubernetes Engine (GKE) 叢集上部署和管理應用程式。它簡化了跨多個叢集的操作,例如流量分割、故障轉移和服務探索,讓您可以更輕鬆地建構和管理高度可用且可擴展的應用程式。
以下是 GKE MCS 的主要功能和優點:
接續第 Day2, Day3,會使用 Day2 創建的 Shared VPC 網路及Day3 的 GKE Terraform,需要再創建一個 GKE 叢集在 US-West4 地區。
GKE Fleet 網路架構表如下:
將讀者的設定取代以下變數內容:
SHARED_VPC_HOST_PROJ
:共用 VPC 宿主專案的 IDFLEET_HOST_PROJ_NUMBER
:艦隊宿主專案的編號,不是專案 ID 唷!FLEET_HOST_PROJ
:集群專案的ID。在艦隊宿主專案中啟用 GKE Hub, Traffic Director、Resource Manager 、Anthos、Cloud DNS 和 Multi-cluster Service Discovery API
$ gcloud services enable gkehub.googleapis.com \
anthos.googleapis.com \
trafficdirector.googleapis.com \
cloudresourcemanager.googleapis.com \
multiclusterservicediscovery.googleapis.com \
dns.googleapis.com \
--project $FLEET_HOST_PROJ
在 SHARED VPC 專案下開啟 Cloud DNS API
$ gcloud services enable dns.googleapis.com \
--project $SHARED_VPC_HOST_PROJ
$ gcloud container fleet multi-cluster-services enable \
--project $FLEET_HOST_PROJ
##輸出
Waiting for Feature Multi-cluster Services to be created...done.
如果在艦隊宿主專案中啟用多集群服務,則系統會創建以下服務帳號或者確保以下服務帳號存在 service-$FLEET_HOST_PROJ_NUMBER@gcp-sa-mcsd.iam.gserviceaccount.com
使用 GKE Fleet 需要開啟 GKE Enterprise 版本,如下圖所示這樣就代表有開啟了。
運行以下命令創建空艦隊
$ gcloud alpha container fleet create --display-name=$NAME --project=$FLEET_HOST_PROJECT
創建完成後,可以在 Fleet Host Project(艦隊宿主專案)下的的 GKE 頁面會看到 Fleet(機群)會顯示出來,而 Cluster(叢集)頁面也會出現 REGISTER(註冊)的選項。
將第一個集群註冊到艦隊。 -gke-cluster
標誌可用於此命令,因為第一個集群與註冊它的艦隊位於同一專案中。
$ gcloud container fleet memberships $叢集名稱_1 \
--project $FLEET所在專案ID \
--enable-workload-identity \
--gke-cluster=$地區/$叢集名稱_1
取代以下內容:
$叢集名稱_1
:此集群在此艦隊中的唯一標識符。 通常使用第一個要註冊的 GKE 集群名稱。$FLEET所在專案ID
:艦隊宿主專案的ID。$地區
:對於可用區級集群,這是包含集群的 Compute Engine 可用區; 對於區域級集群,這是包含集群的 Compute Engine 區域。$叢集名稱_2
:第一個要註冊的叢集的名稱。將第二個集群註冊到艦隊宿主專案。 -gke-cluster
標誌可用於此命令,因為第二個集群也位於艦隊宿主專案中。
$ gcloud container fleet memberships $叢集名稱_2 \
--project $FLEET所在專案ID \
--enable-workload-identity \
--gke-cluster=$地區/$叢集名稱_2
取代以下內容:
$叢集名稱_2
:此集群在此艦隊中的唯一標識符。 通常使用第二個要註冊的 GKE 集群名稱。$FLEET所在專案ID
:艦隊宿主專案的ID。$地區
:對於可用區級集群,這是包含集群的 Compute Engine 可用區; 對於區域級集群,這是包含集群的 Compute Engine 區域。$叢集名稱_2
:第二個要註冊的叢集的名稱。點擊下圖中的註冊,將集群註冊到當前專案中的 Fleet(機群)中
註冊完成後會如下圖顯示叢集所在的機群
再創建一個在 us-west4 的 GKE 叢集,並註冊到此專案中的 Fleet(機群)
創建 IAM 綁定,向艦隊宿主專案 MCS 服務帳號授予共用 VPC 宿主專案的 MCS Service Agent 角色:
$ gcloud projects add-iam-policy-binding $SHARED_VPC_HOST_PROJ \
--member "serviceAccount:service-$FLEET_HOST_PROJ_NUMBER@gcp-sa-mcsd.iam.gserviceaccount.com" \
--role roles/multiclusterservicediscovery.serviceAgent
由於此場景使用適用於 GKE 的工作負載身份聯合,因此艦隊宿主專案的 MCS 導入程式 GKE 服務帳號需要自己專案的 Network User 角色。
創建 IAM 綁定,向艦隊宿主專案 MCS 服務帳號授予自己專案和 Shared VPC 專案的 Network User 角色:
$ gcloud projects add-iam-policy-binding $FLEET_HOST_PROJ \
--member "serviceAccount:$FLEET_HOST_PROJ.svc.id.goog[gke-mcs/gke-mcs-importer]" \
--role roles/compute.networkViewer
$ gcloud projects add-iam-policy-binding $SHARED_VPC_HOST_PROJ \
--member "serviceAccount:$FLEET_HOST_PROJ.svc.id.goog[gke-mcs/gke-mcs-importer]" \
--role roles/compute.networkViewer
可由以下指令驗證是否已啟用 MCS。
$ gcloud container fleet multi-cluster-services describe --project ithome-202409-demo-2
createTime: '2024-10-11T08:57:43.606552889Z'
membershipStates:
projects/407205409614/locations/us-central1/memberships/demo2-cluster:
state:
code: OK
description: Firewall successfully updated
updateTime: '2024-10-13T07:31:59.227720484Z'
projects/407205409614/locations/us-west4/memberships/demo2-us-west4-fleet-cluster:
state:
code: OK
description: Firewall successfully updated
updateTime: '2024-10-13T07:31:58.574210973Z'
name: projects/ithome-202409-demo-2/locations/global/features/multiclusterservicediscovery
resourceState:
state: ACTIVE
spec: {}
updateTime: '2024-10-11T08:57:46.039837503Z'
由輸出可得知兩個集群都已經正常啟用 MCS 了。
同樣 GKE Fleet 的兩個叢集內會創建gke-mcs
NameSpace,並在此 Namespace 下創建 Deployment 及 ServiceAccount,可以到此 Fleet(機群) 下的所有叢集中查看,
$ kubectl get deployment -n gke-mcs
NAME READY UP-TO-DATE AVAILABLE AGE
gke-mcs-importer 1/1 1 1 1m
$ kubectl get sa -n gke-mcs
NAME SECRETS AGE
default 0 1m
gke-mcs-importer 0 1m
下表為本次實驗環境的 GKE Cluster 所有網路相關設定。
GKE Cluster Name | Region | Node IP CIDR | Pod CIDR | Service CIDR |
---|---|---|---|---|
demo2-cluster | us-central1 | 10.120.64.0/20 | 10.120.80.0/20 | 10.120.96.0/20 |
demo2-us-west4-fleet-cluster | us-west4 | 10.123.64.0/20 | 10.123.80.0/20 | 10.123.96.0/20 |
以下使用的鏡像 a51907/display-podname-image:2024 是筆者自己製作可以在前端網頁顯示 Pod 中的環境變數來知道自己的 Pod Name 及 Service Name。
在us-central1
這個地區的集群創建以下 Deployment,有特別標記名稱為 us-central1
。
kubectl apply -f us-central1-deployment.yaml
# us-central1-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: us-central1-deployment
namespace: mcs-test
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: display-podname-image
image: a51907/display-podname-image:2024
ports:
- containerPort: 80
在us-west4
這個地區的集群創建以下 Deployment,有特別標記名稱為 us-west4
。
kubectl apply -f us-west4-deployment.yaml
# us-west4-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: us-west4-deployment
namespace: mcs-test
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: display-podname-image
image: a51907/display-podname-image:2024
ports:
- containerPort: 80
在兩個不同地區的不同集群(us-central1
及us-west4
)都創建上述兩個 Deployment 的 Service 及 ServiceExport
kubectl apply -f mcs-test.yaml
# mcs-test.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: mcs-test
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
---
# serviceexport.yaml
kind: ServiceExport
apiVersion: net.gke.io/v1
metadata:
name: my-service
namespace: mcs-test
等待五分鐘後,系統將會於兩個集群都自動創建 ServiceImport
物件。以下 Tsh 的指令是 Day15 Teleport 介紹,可以快速切換當前的集群。
進入 us-central1 的叢集 demo2-cluster
$ tsh kube login demo2-cluster
$ kubectl get ServiceImport -n mcs-test
NAME TYPE IP AGE
my-service ClusterSetIP ["10.120.102.128"] 8m20s
kubectl get Service -n mcs-test
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
gke-mcs-8b6i2bo58n ClusterIP 10.120.102.128 <none> 80/TCP 53m
my-service ClusterIP 10.120.98.2 <none> 80/TCP 57m
$ kubectl get endpoints gke-mcs-8b6i2bo58n -n mcs-test
NAME ENDPOINTS AGE
gke-mcs-8b6i2bo58n 10.120.80.193:80,10.120.80.71:80,10.123.80.152:80 + 1 more... 54m
進入 us-west4 的叢集 demo2-us-west4-fleet-cluster
$ tsh kube login demo2-us-west4-fleet-cluster
$ kubectl get ServiceImport -n mcs-test
NAME TYPE IP AGE
my-service ClusterSetIP ["10.123.111.156"] 9m
$ kubectl get Service -n mcs-test
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
gke-mcs-8b6i2bo58n ClusterIP 10.123.111.156 <none> 80/TCP 52m
my-service ClusterIP 10.123.97.28 <none> 80/TCP 25m
$ kubectl get endpoints gke-mcs-8b6i2bo58n -n mcs-test
NAME ENDPOINTS AGE
gke-mcs-8b6i2bo58n 10.120.80.193:80,10.120.80.71:80,10.123.80.152:80 + 1 more... 54m
可以發現 ServiceImport 和系統自動創建的 gke-mcs Service 會是同一個 IP,我們去搜索 MCS Service 背後對應的 Endpoint,會發現對應到不同集群中的 Pod IP。
讀者如果設定完後,ServiceImport
, Service
, Endpoints
輸出都如上述所示,恭喜!那就代表設定無誤。此時 GKE Fleet 架構如下圖:
接下來,在兩個不同地區的不同集群(us-central1
及us-west4
)都啟動 radial/busyboxplus:curl 的 pod,待會要使用其來進行 Curl 的指令來確定剛剛創建的 MCS Service 可以正確轉發到不同的集群內
$ kubectl run test-curl --image=radial/busyboxplus:curl -n mcs-test --command -- /bin/sh -c "while true; do sleep 360000; done"
進入上個步驟創建的 Pod 中,請求 K8s 內部的 Service DNS 解析(gke-mcs-8b6i2bo58n.mcs-test.svc.cluster.local:80
)
$ exec kubectl exec -i -t -n mcs-test test-curl -c test-curl -- sh -c "clear; (bash || ash || sh)"
[root@test-curl:/]$ curl http://gke-mcs-8b6i2bo58n.mcs-test.svc.cluster.local:80
可以看到請求到不同地區的 GKE 叢集及不同的 Pod 之中。
由於今年 AI 熱潮導致 GCP 特定區域的 GPU 資源經常短缺,筆者在部署 GPU 叢集時,經常遇到配額不足的問題。由於 GKE 叢集區域固定,若單一節點池(Node Pool)需更換區域,則必須重建整個叢集。為了避免這種情況,並確保 GPU 資源的彈性調度,我們選擇採用 GKE Fleet 的多叢集架構。
這系列的鐵人賽文章也到了第 29 天了,由於篇幅有限,只能帶領讀者體驗 GKE Fleet 的入門,更進階的課題還有 Multi-Cluster Ingress, Multi-Cluster Gateway 這兩項是 Day7 和 Day10 的延伸,以及 Anthos 混合雲和多雲應用程式現代化平台,將不同雲供應商的 K8s Cluster 彼此串接製作成集群艦隊唷!